import RBush from 'rbush';
import worker from 'web-worker:./worker/worker.js';

/**
 * 延迟执行
 * @param fn
 * @returns {(function(): void)|*}
 */
function _debounce(fn) {
  let timeout = null;
  return function() {
    clearTimeout(timeout);
    timeout = setTimeout(() => {
      fn.apply(this, arguments);
    }, 0);
  };
}

// 创建一个自定义的Canvas图层
const LeafletCanvasCircle = L.Canvas.extend({
  _circles: null, // 存储线段数据的数组
  _showCircles: null, // 当前可视范围内的数据
  _worker: null,
  _storageCircles: [],
  /**
   * 提示报错信息
   **/
  promptInfo: {
    layerid_null: 'Layer Id cannot be empty',
    layers_no: 'Current layer not found',
    layers_data_none: 'Data cannot be empty',
  },
  onAdd: function(map) {
    this._map = map;
    this._onClickListeners = [];
    this._onHoverListeners = [];
    this._onMouseDownListeners = [];
    this._onMouseUpListeners = [];
    if (this._circles) {
      // 清空线条数
      this._circles.clear();
      this._showCircles.clear();
    } else {
      this._circles = new RBush();
      this._showCircles = new RBush();
    }
    // 注册worker
    this._worker = new worker();
    // 创建一个新的Canvas元素
    this._canvas = L.DomUtil.create(
        'canvas',
        'leaflet-layer leaflet-canvas-icon-layer',
    );
    this._ctx = this._canvas.getContext('2d');
    this._tempCanvas = document.createElement('canvas');
    this._tempCtx = this._tempCanvas.getContext('2d');
    let animated = this._map.options.zoomAnimation && L.Browser.any3d;
    L.DomUtil.addClass(
        this._canvas,
        'leaflet-zoom-' + (animated ? 'animated' : 'hide'),
    );
    // 将Canvas元素添加到地图上
    this._map._panes.overlayPane.appendChild(this._canvas);
    this._reset(); // 更新Canvas内容
  },
  onRemove: function(map) {
    this.removeAllLayer();
    this._map.getPanes().overlayPane.removeChild(this._canvas);
  },
  _update: function(redraw = true) {
    let seaf = this;
    this._center = this._map.getCenter();
    this._zoom = this._map.getZoom();
    // 先删除
    if (this._showCircles) {
      this._showCircles.clear();
    }
    //地图地理坐标边界
    var mapBounds = this._map.getBounds();
    //适用于runsh的边界对象
    var mapBoxCoords = {
      minX: mapBounds.getWest(),
      minY: mapBounds.getSouth(),
      maxX: mapBounds.getEast(),
      maxY: mapBounds.getNorth(),
    };
    //查询可是范围内的圈
    this._circles.search(mapBoxCoords).forEach(function(e) {
      seaf._computedSize(e.data);
      seaf._showCircles.insert(e);
    });
    requestAnimationFrame(() => {
      this._updateCanvas(redraw);
    });
  },
  /**
   * 获取事件对象
   * 表示给map添加的监听器
   * @return {Object} 监听器/函数键值对
   */
  getEvents: function() {
    var events = {
      viewreset: this._reset, // 首次加载触发
      zoom: this._onZoom,
      moveend: this._reset,  // 完成拖动触发
      click: this._executeListeners, // 点击地图触发
      mousemove: this._executeListeners, // 鼠标移动地图触发
      mousedown: this._executeListeners, // 按下按钮触发
      mouseup: this._executeListeners, // 释放鼠标按钮触发
    };
    if (this._zoomAnimated) {
      events.zoomanim = this._onAnimZoom;
    }
    return events;
  },
  /**
   * 添加click侦听器
   */
  addOnClickListener: function(listener) {
    this._onClickListeners.push(listener);
  },
  /**
   * 添加hover侦听器
   */
  addOnHoverListener: function(listener) {
    this._onHoverListeners.push(listener);
  },

  /**
   * 添加mousedown侦听器
   */
  addOnMouseDownListener: function(listener) {
    this._onMouseDownListeners.push(listener);
  },

  /**
   * 添加mouseup侦听器
   */
  addOnMouseUpListener: function(listener) {
    this._onMouseUpListeners.push(listener);
  },
  /**
   * 执行侦听器
   */
  _executeListeners: function(event) {
    if (!this._showCircles) return;
    var me = this;
    var point = event.containerPoint;
    var x = point.x;
    var y = point.y;
    if (me._openToolTip) {
      me._openToolTip.closeTooltip();
      delete me._openToolTip;
    }
    // 判断是否在圆内
    var ret = me._showCircles.all().filter(function(item) {
      var circle = item.data;
      var center = me._map.latLngToContainerPoint(circle.getLatLng());
      var radius = circle._radius;
      // 计算距离
      var distance = Math.sqrt(
          Math.pow(x - center.x, 2) + Math.pow(y - center.y, 2),
      );
      if (circle.options.sector) {
        var startAngle, endAngle;
        // 当前鼠标角度
        var angle = Math.atan2(y - center.y, x - center.x) * (180 / Math.PI);
        if (circle.options.switch) {
          // 根据朝向角度计算起始角度和结束角度
          startAngle = circle.options.direction - circle.options.angle / 2;
          endAngle = circle.options.direction + circle.options.angle / 2;
        } else {
          // 使用开始角度和结束角度
          startAngle = circle.options.startAngle;
          endAngle = circle.options.endAngle;
        }
        if (startAngle < -180) {
          let calculate = 180 + (startAngle + 180);
          if (angle > calculate) {
            angle = -180 + (calculate - angle);
          }
          // startAngle = startAngle + (-(180 - angle));
        }
        if (endAngle > 180 && startAngle > 0) {
          if (angle < 0 && angle < endAngle) {
            angle = 180 + (angle + 180);
          }
        }
        if (endAngle > 180 && startAngle < 0) {
          let calculate = 180 + (angle + 180);
          if (angle < 0 && calculate < endAngle) {
            angle = calculate;
          }
        }
        if (startAngle <= endAngle) {
          return angle >= startAngle && angle <= endAngle && distance <= radius;
        } else {
          return (
              (angle >= startAngle || angle <= endAngle) && distance <= radius
          );
        }
      } else {
        // 正常圆走这里
        return distance <= radius;
      }
    });
    if (ret && ret.length > 0) {
      me._map._container.style.cursor = 'pointer';
      var topCircle = ret[ret.length - 1].data;
      if (event.type === 'click') {
        var hasPopup = topCircle.getPopup();
        if (hasPopup) topCircle.openPopup();
        me._onClickListeners.forEach(function(listener) {
          listener(event, topCircle);
        });
        return;
      }
      if (event.type === 'mousemove') {
        var hasTooltip = topCircle.getTooltip();
        if (hasTooltip) {
          me._openToolTip = topCircle;
          topCircle.openTooltip();
        }
        me._onHoverListeners.forEach(function(listener) {
          listener(event, topCircle);
        });
        return;
      }
      if (event.type === 'mousedown') {
        // 只返回最上方的图层
        me._onMouseDownListeners.forEach(function(listener) {
          listener(event, topCircle);
        });
        return;
      }
      if (event.type === 'mouseup') {
        // 只返回最上方的图层
        me._onMouseUpListeners.forEach(function(listener) {
          listener(event, topCircle);
        });
        return;
      }
    } else {
      me._map._container.style.cursor = 'default';
    }
  },
  /**
   * 地图Zoomanim事件监听器函数
   * @param ev
   */
  _onAnimZoom(ev) {
    this._updateTransform(ev.center, ev.zoom);
  },
  /**
   * 地图修改zoom事件监听器函数
   */
  _onZoom: function() {
    this._updateTransform(this._map.getCenter(), this._map.getZoom());
  },
  /**
   * 重置画布(大小,位置,内容)
   */
  _reset: function() {
    var topLeft = this._map.containerPointToLayerPoint([0, 0]);
    L.DomUtil.setPosition(this._canvas, topLeft);
    var size = this._map.getSize();
    this._canvas.width = size.x;
    this._canvas.height = size.y;
    this._update();
  },
  /**
   * 修改dom原始的transform或position
   * @param {L/LatLng} center 中心点
   * @param {number} zoom 地图缩放级别
   */
  _updateTransform: function(center, zoom) {
    var scale = this._map.getZoomScale(zoom, this._zoom),
        position = L.DomUtil.getPosition(this._canvas),
        viewHalf = this._map.getSize().multiplyBy(0.5),
        currentCenterPoint = this._map.project(this._map.getCenter(), zoom),
        destCenterPoint = this._map.project(center, zoom),
        centerOffset = destCenterPoint.subtract(currentCenterPoint),
        topLeftOffset = viewHalf.multiplyBy(-scale).
            add(position).
            add(viewHalf).
            subtract(centerOffset);
    if (L.Browser.any3d) {
      L.DomUtil.setTransform(this._canvas, topLeftOffset, scale);
    } else {
      L.DomUtil.setPosition(this._canvas, topLeftOffset);
    }
  },
  _updateCanvas: function(clear = false) {
    let self = this;
    self._ctx.globalCompositeOperation = 'source-over';
    // 使用变量存储所有可见圆形
    let visibleCircles = this._showCircles.all();
    if (this._showCircles.all().length > 0) {
      self.getDraw(visibleCircles, clear);
      return;
    }

    //地图地理坐标边界
    var mapBounds = this._map.getBounds();
    //适用于runsh的边界对象
    var mapBoxCoords = {
      minX: mapBounds.getWest(),
      minY: mapBounds.getSouth(),
      maxX: mapBounds.getEast(),
      maxY: mapBounds.getNorth(),
    };
    let tmp = [];
    this._circles.search(mapBoxCoords).forEach(function(e) {
      tmp.push(e);
    });
    this._showCircles.load(tmp);

    /**
     * 修复中心点不在可视区域内，圆隐藏的问题
     */
    tmp = [...tmp, ...this._isCircleVisible()];
    // 使用 requestAnimationFrame 来绘制
    this.getDraw(tmp, clear);
  },
  getDraw: function(tmp = [], clear = true) {
    let self = this;
    this.draw(tmp, clear);
  },
  /**
   * 采用双缓存技术以防clearRect更新闪屏
   * @returns {Promise<HTMLCanvasElement>}
   */
  draw: function(tmp, clear = false) {
    var self = this;
    let tempCanvas = this._tempCanvas;
    let tempCtx = this._tempCtx;
    let size = self._map.getSize();
    // webwoeker 逻辑
    requestAnimationFrame(() => {
      let newData = [];
      for (let i = 0; i < tmp.length; i++) {
        let item = tmp[i].data;
        let obj = {
          point: {},
          _radius: 0,
        };
        obj.point = this._map.latLngToContainerPoint(item.getLatLng());
        obj._radius = self._computedSize(item);
        let options = {
          ...item.options,
          ...obj,
        };
        delete options.data;
        newData.push(options);
      }
      self._worker.onmessage = function(e) {
        self._storageCircles = tmp;
        if (clear) {
          // 设置宽高
          var canvas = e.data;
          self._ctx.clearRect(0, 0, self._canvas.width, self._canvas.height);
          self._ctx.drawImage(canvas, 0, 0);
        } else {
          var canvas = e.data;
          self._ctx.drawImage(canvas, 0, 0);
        }
      };
      self._worker.postMessage({
        type: 'draw',
        data: newData,
        config: {
          width: size.x,
          height: size.y,
        },
      });
    });
    // 离屏渲染
    // let batchSize = 1000; // 每批绘制的数量
    // let batchCount = Math.ceil(tmp.length / batchSize); // 批次数量
    // requestAnimationFrame(() => {
    //   for (let batch = 0; batch < batchCount; batch++) {
    //     let start = batch * batchSize;
    //     let end = Math.min(start + batchSize, tmp.length);
    //     for (let i = start; i < end; i++) {
    //       let circles = tmp[i].data;
    //       this.redrawCircle(circles);
    //     }
    //   }
    //   self._storageCircles = tmp;
    //   // 将缓存 canvas 复制到旧的 canvas
    //   self._ctx.drawImage(tempCanvas, 0, 0);
    // });
  },
  /**
   * redraw
   * @param circles
   * @param clear
   */
  redrawCircle(circles, clear = false) {
    let tempCtx = this._tempCtx;
    let options = circles.options;
    let {sector} = circles.options;
    let point = this._map.latLngToContainerPoint(circles.getLatLng());
    if (sector) {
      // 绘制扇形
      tempCtx.beginPath();
      tempCtx.moveTo(point.x, point.y);
      var startAngle, endAngle;
      if (options.switch) {
        startAngle = options.direction - options.angle / 2;
        endAngle = options.direction + options.angle / 2;
        startAngle = (startAngle * Math.PI) / 180; // 将角度转换为弧度
        endAngle = (endAngle * Math.PI) / 180; // 将角度转换为弧
      } else {
        startAngle = (options.startAngle * Math.PI) / 180;
        endAngle = (options.endAngle * Math.PI) / 180;
      }
      tempCtx.arc(
          point.x,
          point.y,
          circles._radius,
          startAngle,
          endAngle,
          false,
      );
      tempCtx.lineTo(point.x, point.y);
      tempCtx.closePath();
      if (options.fillOpacity !== 0) {
        // 填充扇形
        tempCtx.fillStyle = options.fillColor;
        tempCtx.globalAlpha = options.fillOpacity;
        tempCtx.fill();
      }
      // 在绘制前设置 lineWidth
      if (tempCtx.previousWeight !== options.weight && options?.opacity !== 0) {
        tempCtx.lineWidth = options.weight;
        tempCtx.previousWeight = options.weight;
      }
      if (options?.opacity !== 0) {
        tempCtx.strokeStyle = options.color;
        tempCtx.globalAlpha = options.opacity || 1;
      }
      // 修复两个条件都不成立黑色描边问题
      if (options?.opacity === 0 && options.fillOpacity === 0) {
        tempCtx.strokeStyle = 'rgba(0,0,0,0)';
      }
      tempCtx.stroke();
    } else {
      tempCtx.beginPath();
      tempCtx.arc(point.x, point.y, circles._radius, 0, Math.PI * 2);
      // 样式
      if (options.fillOpacity !== 0) {
        tempCtx.fillStyle = options.fillColor;
        tempCtx.globalAlpha = options.fillOpacity;
        tempCtx.fill();
      }
      // 在绘制前设置 lineWidth
      if (tempCtx.previousWeight !== options.weight && options?.opacity !== 0) {
        tempCtx.lineWidth = options.weight;
        tempCtx.previousWeight = options.weight;
      }
      if (options?.opacity !== 0) {
        tempCtx.strokeStyle = options.color;
        tempCtx.globalAlpha = options.opacity || 1;
      }
      // 修复两个条件都不成立黑色描边问题
      if (options?.opacity === 0 && options.fillOpacity === 0) {
        tempCtx.strokeStyle = 'rgba(0,0,0,0)';
      }
      tempCtx.stroke();
    }
  },
  /**
   * 根据层级显示圆的大小
   * @param item
   */
  _computedSize: function(item) {
    var lng = item.getLatLng().lng,
        lat = item.getLatLng().lat,
        map = this._map,
        crs = map.options.crs,
        Earth = L.CRS.Earth;
    if (crs.distance === Earth.distance) {
      var d = Math.PI / 180,
          latR = item._mRadius / Earth.R / d,
          top = map.project([lat + latR, lng]),
          bottom = map.project([lat - latR, lng]),
          p = top.add(bottom).divideBy(2),
          lat2 = map.unproject(p).lat,
          lngR =
              Math.acos(
                  (Math.cos(latR * d) - Math.sin(lat * d) *
                      Math.sin(lat2 * d)) /
                  (Math.cos(lat * d) * Math.cos(lat2 * d)),
              ) / d;

      if (isNaN(lngR) || lngR === 0) {
        lngR = latR / Math.cos((Math.PI / 180) * lat); // Fallback for edge case, #2425
      }
      item._point = p.subtract(map.getPixelOrigin());
      item._radius = isNaN(lngR) ? 0 : p.x - map.project([lat2, lng - lngR]).x;
      item._radiusY = p.y - top.y;
      return item._radius;
    }
  },
  /**
   * 添加圆
   * @param {String} id - 图层id
   * @param {Object} config - 基础配置
   * @param {Array} config.data - 经纬度数据 {lat,lng}
   * @param {String} config.color - 线条颜色
   * @param {String} config.weight - 线条粗细
   * @param {String} config.fillColor - 填充颜色
   * @param {String} config.fillOpacity - 填充透明度
   * @param {Boolean} config.sector - 是否是扇形
   * @param {Boolean} config.switch - false 开始角度、结束角度  true 是方向角度
   * @param {Boolean} config.direction -  switc:true 方向
   * @param {Boolean} config.angle -  switc:true 角度
   * @param {Boolean} config.startAngle -  switc:false 开始角度
   * @param {Boolean} config.endAngle -  switc:false 结束角度
   * @param {Boolean} redraw - 是否重绘
   */
  addLayer: function(
      id = '',
      config = {
        data: {},
        color: 'red',
        fillColor: '#f03',
        fillOpacity: 0.5,
        radius: 500,
        weight: 2,
        sector: false,
        switch: false,
        direction: 0,
        angle: 180,
        startAngle: 0,
        endAngle: 90,
      },
      redraw = true,
  ) {
    try {
      let layer = L.circle(config.data, {
        ...{
          color: 'red',
          fillColor: '#f03',
          fillOpacity: 0.5,
          radius: 500,
          weight: 2,
          sector: false,
          switch: false,
          direction: 0,
          angle: 180,
          startAngle: 0,
          endAngle: 90,
        },
        ...config,
      });
      // console.log(layer);
      if (layer.options.sector) {
        if (!layer.options.switch) {
          layer.options.startAngle = layer.options.startAngle - 90;
          layer.options.endAngle = layer.options.endAngle - 90;
        } else {
          layer.options.direction = layer.options.direction - 90;
          layer.options.angle = layer.options.angle;
        }
      }
      layer._map = this._map;
      layer._leaflet_id = id;
      this._computedSize(layer);
      L.Util.stamp(layer);
      var latlng = layer.getLatLng();
      this._circles.insert({
        minX: latlng.lng,
        minY: latlng.lat,
        maxX: latlng.lng,
        maxY: latlng.lat,
        data: layer,
      });
      var isDisplaying = this._map.getBounds().contains(latlng);
      if (redraw && isDisplaying) {
        this._updateCanvas(redraw);
      }
    } catch (err) {
      console.error(err);
    }
  },
  /**
   * 添加多个圆形
   * @param {Array<Object>} list - 圆形的基础配置数组
   * @param {String} list[].id - 图层id
   * @param {Array} list[].data - 经纬度数据 [纬度,经度]
   * @param {String} list[].color - 线条颜色
   * @param {String} list[].weight - 线条粗细
   * @param {String} list[].fillColor - 填充颜色
   * @param {String} list[].fillOpacity - 填充透明度
   * @param {Number} list[].radius - 圆形半径
   * @param {Boolean} list[].sector - 是否是扇形
   * @param {Boolean} list[].switch - false 是经纬度  true 是方向角度
   * @param {Boolean} list[].direction -  switc:true 方向
   * @param {Boolean} list[].angle -  switc:true 角度
   * @param {Boolean} list[].startAngle -  switc:false 开始角度
   * @param {Boolean} list[].endAngle -  switc:false 结束角度
   * @param {Boolean} redraw - 是否重绘
   */
  addLayers: function(list = [], redraw = true) {
    try {
      if (list.length === 0) {
        throw new Error(this.promptInfo.layers_data_none);
      }
      let tmp = [];
      for (let i = 0; i < list.length; i++) {
        let item = list[i];
        let id = JSON.parse(JSON.stringify(item.id));
        delete item.id;
        this.addLayer(id, item, false);
      }
      if (redraw) {
        this._updateCanvas(redraw);
      }
    } catch (err) {
      console.error(err);
    }
  },
  /**
   * 删除某个图层
   * @param {String} layerId - 图层ID
   **/
  removeLayer: function(layerId) {
    try {
      if (!layerId) {
        throw new Error(this.promptInfo.layerid_null);
      }
      let item = this._circles.all().
          find((e) => e.data._leaflet_id === layerId);
      if (item !== -1) {
        let latlng = item.data._latlng;
        var circleData = {
          minX: latlng.lng,
          minY: latlng.lat,
          maxX: latlng.lng,
          maxY: latlng.lat,
          data: item.data,
        };
        this._circles.remove(circleData, function(a, b) {
          return a.data._leaflet_id === b.data._leaflet_id;
        });
        this._update(true);
        return this;
      } else {
        throw new Error(this.promptInfo.layers_no);
      }
    } catch (error) {
      console.error(error);
    }
  },
  /**
   * 删除当前所有图层
   **/
  removeAllLayer() {
    let all = this._circles.all();
    let shwoAll = this._showCircles.all();
    all.map((e) => {
      var hasPopup = e.data.getPopup();
      if (hasPopup) e.data.closePopup();
      e.data.closeTooltip();
    });
    shwoAll.map((e) => {
      var hasPopup = e.data.getPopup();
      if (hasPopup) e.data.closePopup();
      e.data.closeTooltip();
    });
    // 清空线条数组
    this._circles.clear();
    this._showCircles.clear();
    // 更新Canvas内容
    this._update(true);
  },
  /**
   * 更新圆数据
   * @param {String} layerId -线条索引
   * @param {Object} latLng -新坐标
   * @param {Boolean} redraw - 是否重绘
   **/
  setLatLng: function(layerId, latLng = {}, redraw = true) {
    try {
      if (!layerId) {
        throw new Error(this.promptInfo.layerid_null);
      }
      if (layerId && Object.keys(latLng).length > 0) {
        let all = this._circles.all();
        if (all.length > 0) {
          let item = all.
              find((e) => e.data._leaflet_id === layerId);
          if (item !== -1) {
            // 更新 Popup 的位置
            if (item.data._popup) {
              item.data._popup.setLatLng(latLng);
            }
            // 删除
            this._circles.remove(item, function(a, b) {
              return a.data._leaflet_id === b.data._leaflet_id;
            });
            item.data._latlng = latLng;
            var circleData = {
              minX: latLng.lng,
              minY: latLng.lat,
              maxX: latLng.lng,
              maxY: latLng.lat,
              data: item.data,
            };
            // 新增
            this._circles.insert(circleData);
            if (redraw) {
              this._update(redraw);
            }
          } else {
            throw new Error(this.promptInfo.layers_no);
          }
        } else {
          throw new Error(this.promptInfo.layers_no);
        }
      } else {
        throw new Error(this.promptInfo.layers_data_none);
      }
    } catch (error) {
      console.error(error);
    }
  },
  /**
   * 更新圆组数据
   * @param {Array<Object>} list - 圆形的基础配置数组
   * @param {String} list[].id - 图层id
   * @param {Array} list[].data - 经纬度数据 [纬度,经度]
   * @param {Boolean} redraw 是否重绘
   **/
  setLatLngs: function(list = [], redraw = true) {
    try {
      if (list.length > 0) {
        let all = this._circles.all();
        if (all.length > 0) {
          let data = [];
          for (let i = 0; i < list.length; i++) {
            let item = all.
                find((e) => e.data._leaflet_id === list[i].id);
            if (item !== -1) {
              let latlng = list[i].data;

              // 更新 Popup 的位置
              if (item.data._popup) {
                item.data._popup.setLatLng(latLng);
              }
              var circleData = {
                minX: latlng.lng,
                minY: latlng.lat,
                maxX: latlng.lng,
                maxY: latlng.lat,
                data: item.data,
              };

              // 删除
              this._circles.remove(item, function(a, b) {
                return a.data._leaflet_id === b.data._leaflet_id;
              });
              item.data._latlng = latlng;
              // console.log("删除后:",this._circles.all().length);
              data.push(circleData);
            } else {
              throw new Error(this.promptInfo.layers_no);
            }
          }
          // 新增
          this._circles.load(data);
          if (redraw) {
            this._update(redraw);
          }
        } else {
          throw new Error(this.promptInfo.layers_no);
        }
      } else {
        throw new Error(this.promptInfo.layers_data_none);
      }
    } catch (error) {
      console.error(error);
    }
  },
  /**
   * 更新圆样式
   * @param {String} layerId - 图层Id
   * @param {Object} config - 图层样式
   * @param {Boolean} redraw - 重绘
   */
  setStyle: function(layerId = '', config = {}, redraw = true) {
    try {
      if (!layerId) {
        throw new Error(this.promptInfo.layerid_null);
      }
      if (layerId && JSON.stringify(config) !== '{}') {
        let all = this._circles.all();
        if (all.length > 0) {
          let item = this._circles.all().
              find((e) => e.data._leaflet_id === layerId);
          // 改样式就只改样式
          if (config.hasOwnProperty('radius')) {
            delete config.radius;
          }
          if (item !== -1) {
            let latlng = item.data._latlng;
            var circleData = {
              minX: latlng.lng,
              minY: latlng.lat,
              maxX: latlng.lng,
              maxY: latlng.lat,
              data: item.data,
            };
            // 删除
            this._circles.remove(circleData, function(a, b) {
              return a.data._leaflet_id === b.data._leaflet_id;
            });
            // 修复改变Style圆的问题
            for (const configKey in config) {
              if (configKey === 'startAngle') {
                item.data.options[configKey] = config.startAngle - 90;
              } else if (configKey === 'endAngle') {
                item.data.options[configKey] = config.endAngle - 90;
              } else if (configKey === 'direction') {
                item.data.options[configKey] = config.direction - 90;
              } else {
                item.data.options[configKey] = config[configKey];
              }
            }
            // 新增
            this._circles.insert(item);
            if (redraw) {
              this._update(redraw);
            }
          } else {
            throw new Error(this.promptInfo.layers_no);
          }
        } else {
          throw new Error(this.promptInfo.layers_no);
        }
      }
    } catch (error) {
      console.error(error);
    }
  },
  /**
   * 获取圈的半径
   * @param {String} layerId - 图层Id
   */
  getRadius: function(layerId) {
    try {
      if (!layerId) {
        throw new Error(this.promptInfo.layerid_null);
      }
      let all = this._circles.all();
      if (all.length > 0) {
        let item = all.find((e) => e.data._leaflet_id === layerId);
        if (item !== -1) {
          return item.data.getRadius();
        } else {
          throw new Error(this.promptInfo.layers_no);
        }
      } else {
        throw new Error(this.promptInfo.layers_no);
      }
    } catch (err) {
      console.error(err);
    }
  },
  /**
   * 改变圈的大小
   * @param {String} layerId - 图层Id
   * @param {String || Number} radius - 单位(米)
   * @param {Boolean} redraw -重绘
   */
  setRadius: function(layerId, radius, redraw = true) {
    try {
      if (!layerId) {
        throw new Error(this.promptInfo.layerid_null);
      }
      if (!layerId) {
        throw new Error('Please enter the numerical value of the circle');
      }
      let all = this._circles.all();
      if (all.length > 0) {
        let item = all.find((e) => e.data._leaflet_id === layerId);
        if (item !== -1) {
          // 删除
          this._circles.remove(item, function(a, b) {
            return a.data._leaflet_id === b.data._leaflet_id;
          });
          item.data.options.radius = radius;
          item.data._mRadius = radius;
          // 添加
          this._circles.insert(item);
          if (redraw) {
            this._update(redraw);
          }
        } else {
          throw new Error(this.promptInfo.layers_no);
        }
      } else {
        throw new Error(this.promptInfo.layers_no);
      }
    } catch (error) {
      console.error(error);
    }
  },

  /**
   * 根据关键字模糊查询
   * @param  {String} id - 关键字（ID）
   */
  getMatchingData: function(id = '') {
    let data = this._circles.all();
    return data.filter((e) => e.data._leaflet_id.indexOf(id) !== -1).
        map((e) => {
          return {
            id: e.data._leaflet_id,
            ...e.data.options,
          };
        });
  },
  /**
   * 重绘
   * @param {Boolean} redraw - 是否重绘
   */
  redraw: function(redraw = true) {
    if (redraw) {
      this._update(redraw);
    }
  },
  /**
   * 判断当前圈是否在可视区域内
   * @param circle
   * @returns {*}
   * @private
   */
  _isCircleVisible() {
    let self = this;
    let dataOutsideBounds = this._circles.all();
    if (dataOutsideBounds.length === 0) {
      return [];
    }
    // 获取当前地图的可视范围;
    let mapBounds = this._map.getBounds();
    return dataOutsideBounds.filter(e => {
      let circle = e.data;
      if (mapBounds.intersects(circle.getBounds()) &&
          !mapBounds.contains(circle.getLatLng())) {
        return e;
      }
    });
  },
});
L.canvasCircle = function(option) {
  return new LeafletCanvasCircle(option);
};
export default L.canvasCircle;
